package com.tedu.charging.service.bill.service.impl;


import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.tedu.charging.common.core.utils.DateUtils;
import com.tedu.charging.common.pojo.param.UpdateGunStatusParam;
import com.tedu.charging.common.pojo.param.UserGetBalanceParam;
import com.tedu.charging.common.pojo.param.UserUpdateBalanceParam;
import com.tedu.charging.common.pojo.po.GunStationPO;
import com.tedu.charging.common.pojo.vo.VehicleVO;
import com.tedu.charging.common.pojo.web.ServerResult;
import com.tedu.charging.common.pojo.vo.ChargeProgressVO;
import com.tedu.charging.service.bill.dao.BillFailMapper;
import com.tedu.charging.service.bill.dao.BillSuccesMapper;
import com.tedu.charging.service.bill.feignclient.CostClient;
import com.tedu.charging.service.bill.feignclient.DeviceClient;
import com.tedu.charging.service.bill.feignclient.UserClient;
import com.tedu.charging.service.bill.job.ExceptionBillHandleJob;
import com.tedu.charging.service.bill.mqtt.producer.MqttProducer;
import com.tedu.charging.service.bill.pojo.param.BillParam;
import com.tedu.charging.service.bill.pojo.po.BillMQPO;
import com.tedu.charging.service.bill.pojo.po.ChargingBillFail;
import com.tedu.charging.service.bill.pojo.po.ChargingBillSucces;
import com.tedu.charging.service.bill.pojo.vo.BillDetailVO;
import com.tedu.charging.service.bill.config.RabbitMQBillConfig;
import com.tedu.charging.service.bill.pojo.vo.StartChargingCommand;
import com.tedu.charging.service.bill.service.IChargingBillService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.Random;

@Service
//@Lazy
@Slf4j
public class ChargingBillServiceImpl implements IChargingBillService {

    @Autowired
    RabbitTemplate rabbitTemplate;

    @Autowired
    BillSuccesMapper billSuccesMapper;

    @Autowired
    BillFailMapper billFailMapper;


//    @Autowired
//    ChargingUserInfoMapper chargingUserInfoMapper;

    @Autowired
    CostClient costClient;

    @Autowired
    UserClient userClient;

    @Autowired
    DeviceClient deviceClient;

    @Autowired
    MqttProducer mqttProducer;

    @Override
    public boolean chagringFail(String billId) {
        ChargingBillFail chargingBillFail = new ChargingBillFail();
        chargingBillFail.setBillId(billId);
        chargingBillFail.setFailDesc("设备自检失败");
        int insertRow = billFailMapper.insert(chargingBillFail);
        return insertRow >= 1 ? true : false;
    }

    @Override
    public boolean chagringSuccess(String billNumber) {
        ChargingBillSucces chargingBillSucces = new ChargingBillSucces();
        chargingBillSucces.setBillId(billNumber);
        chargingBillSucces.setBillStatus(1);
        chargingBillSucces.setChargingStartTime(new Date());

        int insertRow = billSuccesMapper.insert(chargingBillSucces);

        return insertRow >= 1 ? true : false;
    }

    //创建订单
    @Override
    public String createBill(BillParam billParam) throws Throwable {

        //创建充电订单的订单号
        //生成订单号，订单号不能主键自动加1
        //订单号包含城市编号，时间，随机数
        Random random = new Random();//可以从redis中取编号
        String billId = "100000_" + DateUtils.getTime() + "_" + random.nextInt(100);
        log.debug("billId=" + billId);

        //创建放入消息队列的实体类，类中包含充电场站，车牌等信息
        BillMQPO billMQPO = new BillMQPO();
        BeanUtils.copyProperties(billParam, billMQPO);
        billMQPO.setBillId(billId);
        //调用设备微服务取运营商，充电场站信息
        ServerResult<GunStationPO> gunStationPOServerResult = deviceClient.selectStationByGunId(billParam.getGunId());
        billMQPO.setOperatorId(gunStationPOServerResult.getData().getOperatorId());
        billMQPO.setStationId(gunStationPOServerResult.getData().getStationId());

        //调用用户微服务取车辆信息
        ServerResult<VehicleVO> vehicleServerResult = userClient.getVehicleByUserId(billParam.getUserId());
        billMQPO.setVehicleId(vehicleServerResult.getData().getId());

       //订单放入队列
        rabbitTemplate.convertAndSend(RabbitMQBillConfig.BILL_EXCHANGE, RabbitMQBillConfig.BILL_KEY, billMQPO);

        //调用设备微服务更改枪的状态
        UpdateGunStatusParam updateGunStatusParam = new UpdateGunStatusParam(billParam.getGunId(), 2);
        ServerResult<Boolean> serverResult = deviceClient.updateGunStatus(updateGunStatusParam);
        if (serverResult.getData() == false) {
            throw new Exception("更改订单失败");
        }

        //发开始充电指令给物联网平台
        //创建发给emqx物联网服务器的实体类
        StartChargingCommand startChargingCommand = new StartChargingCommand();
        startChargingCommand.setGunId(billParam.getGunId());
        startChargingCommand.setBillId(billId);
        startChargingCommand.setMsg("start charging");
        String body = JSONObject.toJSONString(startChargingCommand);
        mqttProducer.send(body);


        //创建订单开始充电后，服务器收不到任何消息，需要用定时任务处理。
        //订单放入定时任务
        ExceptionBillHandleJob.setBillSuccesMapper(billSuccesMapper);
        ExceptionBillHandleJob exceptionBillHandleJob = new ExceptionBillHandleJob(billId);
        return billId;
    }


    @Override
    public BillDetailVO normalStopBill(String billId) {
        //得本单费用
        ChargeProgressVO chargeProgressVO = costClient.getCost(billId);

        float totalCast = chargeProgressVO.getTotalCost().floatValue();
        //得用户最新的余额
        Integer userId = chargeProgressVO.getUserId();
        UserGetBalanceParam userGetBalanceParam = new UserGetBalanceParam(userId);
        ServerResult<BigDecimal> serverResult = userClient.getBalance(userGetBalanceParam);
        BigDecimal balance = serverResult.getData();
        balance = balance.subtract(new BigDecimal(Float.toString(totalCast)));

        //更新订单状态
        ChargingBillSucces chargingBillSucces = new ChargingBillSucces();
        chargingBillSucces.setBillStatus(2);
        chargingBillSucces.setChargingEndTime(new Date());
        chargingBillSucces.setPayAmount(new BigDecimal(Float.toString(totalCast)));
        chargingBillSucces.setPayTime(new Date());

        UpdateWrapper updateWrapper = new UpdateWrapper();
        updateWrapper.eq("bill_id", billId);
        billSuccesMapper.update(chargingBillSucces, updateWrapper);

        //更改设备状态
        UpdateGunStatusParam updateGunStatusParam = new UpdateGunStatusParam(chargeProgressVO.getGunId(), 1);
        deviceClient.updateGunStatus(updateGunStatusParam);
        //计算充电详情

        UserUpdateBalanceParam userUpdateBalanceParam = new UserUpdateBalanceParam(userId, balance);
        ServerResult serverResult1 = userClient.upDateBalance(userUpdateBalanceParam);
        BillDetailVO billDetailVO = new BillDetailVO();

        billDetailVO.setHours(chargeProgressVO.getHours());
        billDetailVO.setMinutes(chargeProgressVO.getMinutes());
        billDetailVO.setSeconds(chargeProgressVO.getSeconds());

        billDetailVO.setTotalCost(totalCast);
        billDetailVO.setBalance(balance);
        return billDetailVO;
    }
}
